/**
 * 
 * 模拟目录管理功能
 * 
 * 题目描述

实现一个模拟目录管理功能的软件，输入一个命令序列，输出最后一条命令运行结果。

支持命令：

创建目录命令：mkdir 目录名称，如 mkdir abc 为在当前目录创建abc目录，如果已存在同名目录则不执行任何操作。此命令无输出。
进入目录命令：cd 目录名称，如 cd abc 为进入abc目录，特别地，cd .. 为返回上级目录，如果目录不存在则不执行任何操作。此命令无输出。
查看当前所在路径命令：pwd，输出当前路径字符串。
约束：

目录名称仅支持小写字母；mkdir 和 cd 命令的参数仅支持单个目录，如：mkdir abc 和 cd abc；不支持嵌套路径和绝对路径，如 mkdir abc/efg，cd abc/efg，mkdir /abc/efg，cd /abc/efg 是不支持的。
目录符号为/，根目录/作为初始目录。
任何不符合上述定义的无效命令不做任何处理并且无输出。
输入描述
输入 N 行字符串，每一行字符串是一条命令。

输出描述
输出最后一条命令运行结果字符串。

备注
命令行数限制100行以内，目录名称限制10个字符以内。

用例
输入	mkdir abc
cd abc
pwd
输出	/abc/
说明	在根目录创建一个abc的目录并进入abc目录中查看当前目录路径，输出当前路径/abc/。
 */

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;

/**
  * 
  题目解析
本题感觉主要是考察树形结构定义，以及逻辑模拟。

目录结构，其实就是一个树形结构。一个父目录下面可以有多个直接子目录，而一个子目录只能有一个父目录。因此，本题需要定义出一个多叉树结构。

关于树节点定义如下：

class TreeNode {
        String dicName; // 当前目录的名字
        TreeNode father; // 当前目录的父目录
        List<TreeNode> children; // 当前目录的子目录
}
接下来，就是实现目录管理能力：

mkdir
cd
pwd
实现这三个能力前，我们需要定义出树结构：

class Tree {
        TreeNode root; // 树的根目录
        TreeNode cur; // 当前所在目录
}
其中，tree.cur 用于指向当前所在目录，初始时 tree.cur = tree.root。

mkdir，其实就是在 tree.cur 目录下创建一个子目录，但是前提是 tree.cur 下面不存在对应子目录名，否则不操作。mkdir操作不改变 tree.cur 指向。

cd，有两种情况：

cd ..

cd .. 是返回上级目录（父目录），但是前提是 tree.cur.father 存在，否则不操作。如果 tree.cur.father 存在，则cd .. 会改变 tree.cur = tree.cur.father。
cd 目录名

cd 目录名 是进入子目录，但是前提是 tree.cur 包含对应目录名的子目录，否则不操作。如果 存在对应子目录，则 cd操作会改变 tree.cur = 对应子目录
pwd 是输出当前目录的路径字符串，我们可以不停进行 tree.cur = tree.cur.father 的倒序遍历，获取遍历过程中目录名tree.cur.dicName，直到 tree.cur == NULL。最后拼接时注意反转。

上面是目录管理功能的三个能力大致实现思路，具体实现根据不同语言有不同改进，比如 cd 目录名 功能，我们需要遍历 tree.cur.children 来确认对应目录名是否存在，这里Java，JS，Py定义 tree.cur.children 时可以使用 字典Map 来定义（key是目录名，val是对应目录名的TreeNode），从而实现快速查找对应目录。

另外，本题需要对mkdir, cd, pwd的命令参数做约束：

mkdir, cd 的参数只能是1个，如果超过1个，就不进行操作
pwd 不需要参数，如果有参数，就不进行操作
mkdir，cd的参数（目录名）只能由小写字母组成，否则不操作
mkdir，cd的参数（目录名）不能是嵌套路径，或者绝对路径

  */
public class 模拟目录管理功能 {
    
    public static void main(String[] args) {


        try{

            Scanner scanner = new Scanner(System.in);

            //构建目录树
            Tree tree = new Tree();

            String lastCommandOutPut = "/";

            outer:
            while (scanner.hasNextLine()) {

                //获取命令
                String commandStr = scanner.nextLine();

                //System.out.println("接收到的命令="+commandStr);

                if(commandStr.equals(""))  break;

                String[] commandSpilt = commandStr.split(" ");

                if(commandSpilt[0].equals("pwd")){

                    if(commandSpilt.length > 1) continue;

                    lastCommandOutPut = tree.pwd();

                    //System.out.println(lastCommandOutPut);

                } else if(commandSpilt[0].equals("cd") || commandSpilt[0].equals("mkdir")){

                    if(commandSpilt.length != 2) continue;

                    //参数
                    String params = commandSpilt[1];

                    if(commandSpilt[0].equals("cd")){

                        if(!params.equals("..")){

                            //参数校验
                            // 目录名约束校验
                            // 约束：目录名称仅支持小写字母
                            // 约束：不支持嵌套路径和绝对路径，如 mkdir abc/efg，cd abc/efg，mkdir /abc/efg，cd /abc/efg 是不支持的。
                            // 关于嵌套路径和绝对路径，我简单理解就是cmd_val含有'/'字符，可以被小写字母判断涵盖住
                            for (char c : params.toCharArray()) {
                                if (c < 'a' || c > 'z') continue outer;
                            }
                        }

                        tree.cd(params);

                    } else{

                        if(!params.equals("..")){

                            //参数校验
                            // 目录名约束校验
                            // 约束：目录名称仅支持小写字母
                            // 约束：不支持嵌套路径和绝对路径，如 mkdir abc/efg，cd abc/efg，mkdir /abc/efg，cd /abc/efg 是不支持的。
                            // 关于嵌套路径和绝对路径，我简单理解就是cmd_val含有'/'字符，可以被小写字母判断涵盖住
                            for (char c : params.toCharArray()) {
                                if (c < 'a' || c > 'z') continue outer;
                            }
                        }

                        tree.mkdir(params);

                    }


                }

            }

            System.out.println(lastCommandOutPut);

        }catch(Exception e){
            e.printStackTrace();
        }


    }

    private static class TreeNode{

        public String nodeName;
        public TreeNode parentNode;
        Map<String, TreeNode> childs;

        public TreeNode(String nodeName, TreeNode parent){
            this.nodeName = nodeName;
            this.parentNode = parent;
            childs = new HashMap<>();
        }

    }

    private static class Tree{

        TreeNode rootNode;
        TreeNode curNode;

        public Tree(){

            this.rootNode = new TreeNode("/", null);
            this.curNode = rootNode;

        }

        //创建目录
        public void mkdir(String nodeName){

            //mkdir 目录名称，如 mkdir abc 为在当前目录创建abc目录，如果已存在同名目录则不执行任何操作
            this.curNode.childs.putIfAbsent(nodeName, new TreeNode(nodeName+"/", this.curNode));
        }

        public void cd(String dicName){

            if("..".equals(dicName)){

                //返回上层
                if(this.curNode.parentNode != null){
                    this.curNode = this.curNode.parentNode;
                }
            } else {

                if(this.curNode.childs.containsKey(dicName)){
                    this.curNode = this.curNode.childs.get(dicName);
                }


            }
        }

        public String pwd(){
            // 输出当前路径字符串
            StringBuilder builder = new StringBuilder();

            // 倒序路径，即不停向上找父目录
            TreeNode cur = this.curNode;
            while (cur != null) {
                // 头插目录名，保证路径中目录层级正确
                builder.insert(0, cur.nodeName);
                cur = cur.parentNode;
            }
 
            return builder.toString();

        }

    }
}
